package com.mz.mattress.client.plan;

import com.mz.mattress.api.entity.PlanDate;
import com.mz.mattress.api.entity.PlanSendTaskRecord;
import com.mz.mattress.api.entity.PlanTaskData;
import com.mz.mattress.api.enums.TaskStatusEnum;
import com.mz.mattress.api.redis.RedisKeys;
import com.mz.mattress.api.util.DateUtil;
import com.mz.mattress.client.mapper.*;
import com.mz.mattress.client.service.PlanDateService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.*;

/**
 * 按时间段，每个时间段（15分钟）应该下发多少任务
 */
@Slf4j
@Service
public class PlanTimerService implements PlanTimer {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private PlanTaskDataMapper planTaskDataMapper;

    @Autowired
    private PlanDateMapper planDateMapper;

    @Autowired
    private PlanDateService planDateService;

    @Autowired
    private PlanSendTaskRecordMapper planSendTaskRecordMapper;

    public static final ScheduledExecutorService EXECUTOR = new ScheduledThreadPoolExecutor(1, new ThreadFactory() {
        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(r);
            t.setName("planTimerThread");
            t.setDaemon(true);
            return t;
        }
    });

    @PostConstruct
    public void init() {

        int delay = isTest ? 1 : PlanTimer.TIME_SPAN;

        EXECUTOR.scheduleWithFixedDelay(new Runnable() {
            @Override
            public void run() {

                runTask();

            }
        }, delay, delay, TimeUnit.MINUTES);

    }


    @Override
    public void runTask() {

        initDeviceQueue();

        initOldMobile();

        initCreateOrderData();

        initCheckedOrder();

        sendTask(null);

        sendCheckTask(null);

    }

    public void initCheckedOrder() {

        try {
            planDateService.initCheckedOrder();
        } catch (Throwable e) {
            log.error("plan_timer_error", e);
        }

    }

    public void initDeviceQueue() {

        try {
            planDateService.initDeviceQueue();
        } catch (Throwable e) {
            log.error("plan_timer_error", e);
        }

    }

    /**
     * 初始化留存手机号队列
     */
    public void initOldMobile() {

        try {
            planDateService.initOldMobile();
        } catch (Throwable e) {
            log.error("plan_timer_error", e);
        }

    }

    public void initCreateOrderData() {

        try {
            planDateService.initCreateOrderData();
        } catch (Throwable e) {
            log.error("plan_timer_error", e);
        }

    }

    public void sendTask(Integer count) {
        try {

            log.info("plan_timer_running");

            String nowDate = DateUtil.getNowDate();

            //定义任务类型
            PlanTypeEnum planTypeEnum = PlanTypeEnum.CREATE_ORDER;

            PlanDate planDate = planDateMapper.selectByDates(nowDate);
            if (planDate == null) {
                log.error("plan_timer_date_not_found");
                return;
            }

            Integer orderTotal = planDate.getOrderTotal();
            if (orderTotal == null || orderTotal == 0) {
                log.error("plan_timer_total_count=0");
                return;
            }
            LocalDateTime now = LocalDateTime.now();

            LocalTime time = LocalTime.of(now.getHour(), now.getMinute());

            Integer hand = 1;
            if (count == null) {
                count = isTest ? 1 : TaskNumCalculate.calculateTaskCount(time, orderTotal);
                hand = 0;
            }

            log.info("plan_timer_count=" + count);

            int max = PlanTimer.TIME_SPAN * 60;

            for (int i = 0; i < count; i++) {

                //900=60*15
                //最大多少秒
                int delayTime = isTest ? 1 : ThreadLocalRandom.current().nextInt(max - 10) + 10;

                PlanTaskData taskData = new PlanTaskData();
                taskData.setDates(nowDate);
                taskData.setBeanName(planTypeEnum.getBeanName());
                taskData.setType(planTypeEnum.getType());
                taskData.setTotalStep(planTypeEnum.getTotalStep());
                taskData.setCurStep(0);
                taskData.setStatus(TaskStatusEnum.INIT.getValue());
                taskData.setDelayTime(delayTime);
                planTaskDataMapper.insert(taskData);

                //放入延迟队列
                redisTemplate.opsForZSet().
                        add(RedisKeys.PLAN_TASK_SCORE_QUEUE, taskData.getId(),
                                (delayTime * 1000) + System.currentTimeMillis());

                log.info("plan_timer_add_taskId={},delayTime={}", taskData.getId(), delayTime);
            }

            if (count > 0) {
                PlanSendTaskRecord record = new PlanSendTaskRecord();
                record.setType(planTypeEnum.getType());
                record.setCount(count);
                record.setHand(hand);
                planSendTaskRecordMapper.insert(record);
            }

        } catch (Throwable e) {
            log.error("plan_timer_error", e);
        }

    }

    //发放核销任务
    public void sendCheckTask(Integer count) {
        try {

            log.info("plan_timer_check_order_running");

            String nowDate = DateUtil.getNowDate();

            //定义任务类型
            PlanTypeEnum planTypeEnum = PlanTypeEnum.CHECK_ORDER;

            PlanDate planDate = planDateMapper.selectByDates(nowDate);
            if (planDate == null) {
                log.error("plan_timer_check_order_date_not_found");
                return;
            }

            Integer orderTotal = planDate.getOldOrderCount();
            if (orderTotal == null || orderTotal == 0) {
                log.error("plan_timer_check_order_total_count=0");
                return;
            }
            LocalDateTime now = LocalDateTime.now();

            LocalTime time = LocalTime.of(now.getHour(), now.getMinute());

            Integer hand = 1;
            if (count == null) {
                count = isTest ? 1 : TaskNumCalculate.calculateTaskCount(time, orderTotal);
                hand = 0;
            }

            log.info("plan_timer_check_order_count=" + count);

            int max = PlanTimer.TIME_SPAN * 60;

            for (int i = 0; i < count; i++) {

                //900=60*15
                //最大多少秒
                int delayTime = isTest ? 1 : ThreadLocalRandom.current().nextInt(max - 10) + 10;

                Object object = redisTemplate.boundListOps(RedisKeys.CHECKED_ORDER_ID_QUEUE).leftPop();
                if (object == null) {
                    log.info("plan_timer_check_order_no_orderId");
                    return;
                }

                Long orderId = (Long) object;

                PlanTaskData taskData = new PlanTaskData();
                taskData.setDates(nowDate);
                taskData.setBeanName(planTypeEnum.getBeanName());
                taskData.setType(planTypeEnum.getType());
                taskData.setTotalStep(planTypeEnum.getTotalStep());
                taskData.setOrderId(orderId);
                taskData.setCurStep(0);
                taskData.setStatus(TaskStatusEnum.INIT.getValue());
                taskData.setDelayTime(delayTime);
                planTaskDataMapper.insert(taskData);

                //放入延迟队列
                redisTemplate.opsForZSet().
                        add(RedisKeys.PLAN_TASK_SCORE_QUEUE, taskData.getId(),
                                (delayTime * 1000) + System.currentTimeMillis());

                log.info("plan_timer_check_order_add_taskId={},delayTime={}", taskData.getId(), delayTime);
            }

            if (count > 0) {
                PlanSendTaskRecord record = new PlanSendTaskRecord();
                record.setType(planTypeEnum.getType());
                record.setCount(count);
                record.setHand(hand);
                planSendTaskRecordMapper.insert(record);
            }

        } catch (Throwable e) {
            log.error("plan_timer_check_order_error", e);
        }

    }

    public static void main(String[] args) {

        List<Integer> list = new ArrayList<>(20);

        for (int i = 0; i < 20; i++) {
            list.add(i);
        }

        int step = 6;

        for (int i = 0; i < list.size(); i = i + step) {

            int max = i + step;
            if (max > list.size()) {
                max = list.size();
            }

            List<Integer> subList = list.subList(i, max);
            System.out.println(Arrays.toString(subList.toArray()));
        }

    }
}
